﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using Anagramme.Contracts;

namespace Anagramme.Model
{
    /// <summary>
    /// Modèle de la partie
    /// </summary>
    [Export(typeof(IService))]
    [Export(typeof(IGameModel))]
    [Export(typeof(IDisposable))]
    public sealed class GameModel : ModelBase<IGameService>, IGameModel, IGameServiceCallback
    {
        #region IGameService Implementation
        /// <summary>
        /// Authentifie le client sur le service
        /// </summary>
        /// <param name="token">Jeton de sécurité</param>
        /// <remarks>Le jeton de sécurité est obtenu lors de la connexion au service de lobby</remarks>
        public void Authenticate(Guid token)
        {
            base.Service.Authenticate(token);
        }
        
        /// <summary>
        /// Envoie d'une demande pour récupérer les informations sur l'équipe Bleue
        /// </summary>
        public void RequestGameBlueTeamInfos()
        {
            base.Service.RequestGameBlueTeamInfos();
        }

        /// <summary>
        /// Envoie d'une demande d'extinction du serveur
        /// </summary>
        /// <remarks>Nécessite d'être le maitre du lobby</remarks>
        public void RequestGameClose()
        {
            base.Service.RequestGameClose();
        }

        /// <summary>
        /// Envoie d'une demande pour récupérer les informations sur la partie
        /// </summary>
        public void RequestGameInfos()
        {
            base.Service.RequestGameInfos();
        }

        /// <summary>
        /// Indique au serveur que le joueur quitte la partie
        /// </summary>
        public void RequestGameLeave()
        {
            base.Service.RequestGameLeave();
        }

        /// <summary>
        /// Indique au serveur que le jeu à été chargé sur le client
        /// </summary>
        public void RequestGameLoaded()
        {
            base.Service.RequestGameLoaded();
        }

        /// <summary>
        /// Envoie d'une demande pour récupérer les informations sur l'équipe Rouge
        /// </summary>
        public void RequestGameRedTeamInfos()
        {
            base.Service.RequestGameRedTeamInfos();
        }

        /// <summary>
        /// Envoie d'une demande de soumission d'un mot
        /// </summary>
        /// <param name="wordNumber">Index du mot à contrôler</param>
        /// <param name="word">Mot à comparer</param>
        /// <remarks>La comparaison des mots n'est ni sensible à la casse, ni aux accents</remarks>
        public void RequestGameSubmitWord(int wordNumber, string word)
        {
            base.Service.RequestGameSubmitWord(wordNumber, word);
        }
        #endregion

        #region IGameModel Implementation
        /// <summary>
        /// Se produit lors de la récupération des informations sur l'équipe Bleue
        /// </summary>
        public event EventHandler<EventArgs<Team>> OnResponseGameBlueTeamInfos;

        /// <summary>
        /// Se produit lorsque le serveur à été arrêté
        /// </summary>
        public event EventHandler<EventArgs> OnResponseGameDisconnect;

        /// <summary>
        /// Se produit lors de la fin du jeu
        /// </summary>
        public event EventHandler<EventArgs> OnResponseGameFinished;

        /// <summary>
        /// Se produit lors de la modification du score d'une équipe
        /// </summary>
        public event EventHandler<EventArgs<int, int>> OnResponseGameIncreaseTeamScore;

        /// <summary>
        /// Se produit lors de la récupération des informations de la partie
        /// </summary>
        public event EventHandler<EventArgs<GameInfo>> OnResponseGameInfos;

        /// <summary>
        /// Se produit lorsqu'un joueur quitte la partie
        /// </summary>
        public event EventHandler<EventArgs<int>> OnResponseGamePlayerLeave;

        /// <summary>
        /// Se produit lors de la récupération des informations du round courant
        /// </summary>
        public event EventHandler<EventArgs<RoundInfo>> OnResponseGameNewRound;

        /// <summary>
        /// Se produit lors de la récupération des informations sur l'équipe Rouge
        /// </summary>
        public event EventHandler<EventArgs<Team>> OnResponseGameRedTeamInfos;

        /// <summary>
        /// Se produit lors de la fin du round
        /// </summary>
        public event EventHandler OnResponseGameRoundFinished;

        /// <summary>
        /// Se produit lorsqu'un mot à été découvert par l'adversaire
        /// </summary>
        public event EventHandler<EventArgs<int>> OnResponseGameWordFound;

        /// <summary>
        /// Se produit lors de la réponse à la soumission d'un mot
        /// </summary>
        public event EventHandler<EventArgs<int, bool>> OnResponseGameWordSubmit;
        #endregion

        #region IGameServiceCallback Implementation
        void IGameServiceCallback.ResponseGameBlueTeamInfos(Team team)
        {
            if (OnResponseGameBlueTeamInfos != null)
                OnResponseGameBlueTeamInfos(this, new EventArgs<Team>(team));
        }

        void IGameServiceCallback.ResponseGameDisconnect()
        {
            if (OnResponseGameDisconnect != null)
                OnResponseGameDisconnect(this, EventArgs.Empty);
        }

        void IGameServiceCallback.ResponseGameFinished()
        {
            if (OnResponseGameFinished != null)
                OnResponseGameFinished(this, EventArgs.Empty);
        }

        void IGameServiceCallback.ResponseGameIncreaseTeamScore(int teamId, int score)
        {
            if (OnResponseGameIncreaseTeamScore != null)
                OnResponseGameIncreaseTeamScore(this, new EventArgs<int, int>(teamId, score));
        }

        void IGameServiceCallback.ResponseGameInfos(GameInfo infos)
        {
            if (OnResponseGameInfos != null)
                OnResponseGameInfos(this, new EventArgs<GameInfo>(infos));
        }

        void IGameServiceCallback.ResponseGameNewRound(RoundInfo infos)
        {
            if (OnResponseGameNewRound != null)
                OnResponseGameNewRound(this, new EventArgs<RoundInfo>(infos));
        }

        void IGameServiceCallback.ResponseGamePlayerLeave(int playerId)
        {
            if (OnResponseGamePlayerLeave != null)
                OnResponseGamePlayerLeave(this, new EventArgs<int>(playerId));
        }

        void IGameServiceCallback.ResponseGameRedTeamInfos(Team team)
        {
            if (OnResponseGameRedTeamInfos != null)
                OnResponseGameRedTeamInfos(this, new EventArgs<Team>(team));
        }

        void IGameServiceCallback.ResponseGameRoundFinished()
        {
            if (OnResponseGameRoundFinished != null)
                OnResponseGameRoundFinished(this, EventArgs.Empty);
        }

        void IGameServiceCallback.ResponseGameWordFound(int wordNumber)
        {
            if (OnResponseGameWordFound != null)
                OnResponseGameWordFound(this, new EventArgs<int>(wordNumber));
        }

        void IGameServiceCallback.ResponseGameWordSubmit(int wordNumber, bool result)
        {
            if (OnResponseGameWordSubmit != null)
                OnResponseGameWordSubmit(this, new EventArgs<int, bool>(wordNumber, result));
        }
        #endregion
    }
}
